<?php
/**
 * Author: ChenGuangHui
 * Email：13035809409@163.com
 * Date Time: 2021/7/15 17:56
 */


namespace App\Logic\Notice;


use App\Enums\HttpCode;
use App\Logic\CommLogic;
use App\Models\Common\AuthClump;
use App\Models\Notice\Notice;
use App\Models\Notice\NoticeClass;
use App\Models\Notice\NoticeToStaffer;
use App\Services\CommonService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\QueryException;

class NoticeLogic extends CommLogic
{
    /**
     * @param $params
     * @return array
     */
    public function lists($params)
    {
        $list = Notice::query()
            ->where(function (Builder $query) {
                $query->where('created_id', auth('api')->id());
            })->orWhere(function (Builder $query) {
                $query->whereHas('staffer', function (Builder $query) {
                    $query->where('staffer_id', auth('api')->id());
                });
            })
            ->orderByDesc('created_at')
            ->get()
            ->toArray();

        $draftBox = collect($list)->where('created_id', auth('api')->id())->where('status', 0)->all();
        $unread = collect($list)->where('created_at', '>', date('Y-m-d H:i:s', strtotime('-7 days')))->where('status', 0)->all();
        $recycle = Notice::withTrashed()->where(function (Builder $query) {
            $query->where('created_id', auth('api')->id());
        })->orWhere(function (Builder $query) {
            $query->whereHas('staffer', function (Builder $query) {
                $query->where('staffer_id', auth('api')->id());
            });
        })->orderByDesc('created_at')->get()->toArray();

        return array(
            'station' => $this->_getClassNotice(NoticeClass::query()->get()->toArray()),
            'recycle' => $recycle,
            'unread' => array_values($unread),
            'draft_box' => array_values($draftBox),
        );
    }

    /**
     * @param $class
     * @return mixed
     */
    public function _getClassNotice($class)
    {
        $notice = Notice::query()->whereIn('class_id', array_column($class, 'id'))->whereHas('staffer', function (Builder $query) {
            $query->where('staffer_id', auth('api')->id());
        })->get()->groupBy('class_id')->toArray();

        foreach ($class as &$item) {
            $item['children'] = isset($notice[$item['id']]) ? $notice[$item['id']] : [];
        }

        return $class;
    }

    /**
     * @param $params
     * @return array
     */
    public function index($params)
    {
        $notice = Notice::query()
            ->where('status', 1)
            ->whereHas('staffer', function (Builder $query) {
                $query->where('staffer_id', auth('api')->id());
            })
            ->orderByDesc('created_at')
            ->get()
            ->toArray();
        foreach ($notice as &$item) {
            $item['date'] = date('Y-m-d', strtotime($item['created_at']));
        }
        return $notice;
    }

    /**
     * @param $id
     * @return \App\Models\Model|Builder|\Illuminate\Database\Eloquent\Model|object|null
     */
    public function show($id)
    {
        $notice = Notice::query()->where('id', $id)->first();
        abort_if(empty($notice), HttpCode::FORBIDDEN, '消息不存在！');
        NoticeToStaffer::query()->where('notice_id', $id)->where('staffer_id', auth('api')->id())->update(['is_red' => 1]);
        return $notice;
    }

    /**
     * @param $params
     * @return Notice|Builder|\Illuminate\Database\Eloquent\Model
     * @throws \Throwable
     */
    public function store($params)
    {
        $lockName = 'notice_store_' . auth('api')->id();
        $lock = \Cache::lock($lockName, 5);
        abort_if(!$lock->get(), HttpCode::TOO_MANY_REQUESTS, '请勿重复操作！');
        \DB::beginTransaction();
        try {
            $data = array(
                'title' => $params['title'],
                'class_id' => $params['class_id'],
                'abstract' => substr($params['content'], 0, 250),
                'status' => $params['status'],
                'content' => $params['content'],
                'md_content' => $params['md_content']
            );
            $notice = Notice::query()->create($data);
            $data = array();
            foreach ($notice['clump_ids'] as $stafferId) {
                $data[] = array(
                    'staffer_id' => $stafferId['id'],
                    'notice_id' => $notice->getQueueableId()
                );
            }
            NoticeToStaffer::query()->insert($data);
            \DB::commit();
            return $notice;
        } catch (QueryException $exception) {
            \DB::rollBack();
            throw new \Exception($exception->getMessage(), $exception->getCode());
        }
    }

    /**
     * 5分钟内发送的消息可撤回
     * @param $id
     * @return bool
     */
    public function cancel($id)
    {
        $lockName = 'notice_cancel_' . auth('api')->id();
        $lock = \Cache::lock($lockName, 5);
        abort_if(!$lock->get(), HttpCode::TOO_MANY_REQUESTS, '请勿重复操作！');
        $notice = Notice::query()->where('id', $id)->first();
        abort_if(empty($notice), HttpCode::FORBIDDEN, '消息不存在！');
        abort_if($notice->created_id <> auth('api')->id(), HttpCode::FORBIDDEN, '非本人发布不可撤回！');
        abort_if($notice->status <> 0, HttpCode::FORBIDDEN, "当前状态不可撤回！");
        Notice::query()->where('id', $id)->update(['status' => 0]);
        return true;
    }

    /**
     * @param $id
     * @return bool|null
     */
    public function rollback($id)
    {
        $lockName = 'notice_rollback_' . auth('api')->id();
        $lock = \Cache::lock($lockName, 5);
        abort_if(!$lock->get(), HttpCode::TOO_MANY_REQUESTS, '请勿重复操作！');
        $notice = Notice::withTrashed()->where('id', $id)->first();
        abort_if(empty($notice), HttpCode::FORBIDDEN, '消息不存在！');
        return $notice->restore();
    }

    /**
     * @param $id
     * @return bool
     * @throws \Throwable
     */
    public function destroy($id)
    {
        $data = Notice::query()->where('id', $id)->first();
        abort_if(empty($data), HttpCode::FORBIDDEN, '找不到消息');
        \DB::beginTransaction();
        try {
            NoticeToStaffer::query()->where('notice_id', $id)->where('staffer_id', auth('api')->id())->delete();
            \DB::commit();
        } catch (QueryException $exception) {
            \DB::rollBack();
            throw new \Exception($exception->getMessage(), $exception->getCode());
        }
        return true;
    }
}
